package com.wofish.oauth.controller;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.wofish.common.core.domain.JsonRsp;
import com.wofish.core.annotation.LoginToken;
import com.wofish.core.dto.BusiStatus;
import com.wofish.core.redis.JedisService;
import com.wofish.oauth.account.domain.MemberAccount;
import com.wofish.oauth.account.service.IMemberAccountService;
import com.wofish.oauth.dto.LoginParam;
import com.wofish.oauth.dto.TokenParam;
import com.wofish.oauth.exception.UnauthorizedException;
import com.wofish.oauth.shiro.ShiroKit;
import com.wofish.oauth.util.JWTUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;

/**
 * 登录接口类
 */
@Slf4j
@RestController
@RequestMapping("/api/v1/oauth")
public class LoginController extends BaseController{

    @Autowired
    private JedisService jedisService;

    @Autowired
    private IMemberAccountService memberAccountService;


    @PostMapping("/login")
    public JsonRsp<Map<String,Object>> login(@RequestBody LoginParam loginParam) {
        log.info("用户请求登录获取Token");
        String username = loginParam.getUsername();
        String password = loginParam.getPassword();
        MemberAccount user = memberAccountService.findAccountByUsername(username);
        if(user == null){
            return new JsonRsp<>(BUSI_ERROR, BusiStatus.USER_ERROR.getDesc());
        }
        //随机数盐
        String salt = user.getSalt();
        //原密码加密（通过username + salt作为盐）
        String encodedPassword = ShiroKit.md5(password, username + salt);
        if (user.getPassword().equals(encodedPassword)) {
            Map<String, Object> data = storeTokenData(user);
            JsonRsp<Map<String,Object>> jsonRsp = new JsonRsp<>(BUSI_NORMAL, true, "success", data);
            return jsonRsp;
        } else {
            throw new UnauthorizedException();
        }
    }


    @PostMapping("/refresh")
    public JsonRsp<Map<String,Object>> login(@Valid @RequestBody TokenParam tokenParam) {
        log.info("用户请求刷新refreshToken");
        JsonRsp jsonRsp = new JsonRsp();

        String memberId = jedisService.get(tokenParam.getRefreshToken());
        if(StringUtils.isBlank(memberId)){
            jsonRsp.setCode(BusiStatus.REFRESH_TOKEN_EXPIRE.value());
            jsonRsp.setMsg(BusiStatus.REFRESH_TOKEN_EXPIRE.getDesc());
            return jsonRsp;
        }


        MemberAccount user = memberAccountService.selectMemberAccountById(Long.valueOf(memberId));
        if (user == null) {
            throw new UnauthorizedException(BusiStatus.USER_NOT_EXIST.getDesc(),BusiStatus.USER_NOT_EXIST.value());
        }
        // 验证 token
        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword()+user.getSalt())).build();
        try {
            jwtVerifier.verify(tokenParam.getRefreshToken());
        } catch (JWTVerificationException e) {
            throw new UnauthorizedException("resource permission",401);
        }

        String tokenUid = JWT.decode(tokenParam.getToken()).getClaim("uid").asString();
        String refreshTokenUid = JWT.decode(tokenParam.getRefreshToken()).getClaim("uid").asString();
        if(tokenUid.equals(refreshTokenUid)){
            Map<String, Object> data = storeTokenData(user);
            jsonRsp = new JsonRsp<>(BUSI_NORMAL, true, "success", data);
        }else {
            throw new UnauthorizedException("resource permission",401);
        }

        return jsonRsp;

    }


    private Map<String,Object> storeTokenData(MemberAccount user){
        //生成token，同时写入到redis
        String accessToken = JWTUtil.sign(user.getApp(),user.getMemberId(), user.getPassword());
        String refreshToken = JWTUtil.sign(user.getApp(),user.getMemberId(),  user.getPassword()  + System.currentTimeMillis());
        //写入到redis
        jedisService.set(String.valueOf(user.getMemberId()),accessToken,JWTUtil.TOKEN_EXPIRE_TIME);
        jedisService.set(String.valueOf(user.getMemberId()),refreshToken,JWTUtil.REFRESH_TOKEN_EXPIRE_TIME);

        Map<String,Object> data = new HashMap<>();
        data.put("accessToken",accessToken);
        data.put("refreshToken",refreshToken);

        return data;
    }



    @GetMapping("/test")
    public String test() {
        return "test";
    }

    @LoginToken
    @GetMapping("/getMessage")
    public String getMessage(){
        return "你已通过验证";
    }

}
